import { BattlePlayer } from './BattlePlayer';
import { MapSettings, BasePositionConfigs } from './Const';
import { PlayerType, TildeType } from './Enums';
import { BuildingModel, TildeModel, UnitModel } from './Model';

export class BattleMap {
    public map: TildeModel[][] = [];
    // 玩家管理
    private players: Map<string, BattlePlayer> = new Map();

    public constructor(playerIds: string[], numericMap: number[][], mapType: string) {
        this.initMap(numericMap);
        this.initPlayers(playerIds, mapType);
    }

    public initMap(numericMap: number[][]) {
        // 根据传入的numericMap生成地图
        for (let y = 0; y < numericMap.length; y++) {
            this.map[y] = [];
            for (let x = 0; x < numericMap[y].length; x++) {
                // 根据numericMap的值设置地形类型：0是平地，1是山丘
                this.map[y][x] = {
                    type: numericMap[y][x] as TildeType,
                };
            }
        }
    }

    /**
     * 初始化玩家
     */
    private initPlayers(playerIds: string[], mapType: string): void {
        playerIds.forEach((playerId, index) => {
            const playerType = index === 0 ? PlayerType.PLAYER1 : PlayerType.PLAYER2;
            const color = index === 0 ? MapSettings.playerColors[0] : MapSettings.playerColors[1];
            const startPosition = BasePositionConfigs[mapType][index];

            const player = new BattlePlayer(playerId, playerType, color, startPosition);
            this.players.set(playerId, player);
        });
    }

    /**
     * 获取地形地图
     * @returns 数字格式的地图数据
     */
    public getNumericMap(): number[][] {
        const numericMap: number[][] = [];
        for (let y = 0; y < this.map.length; y++) {
            numericMap[y] = [];
            for (let x = 0; x < this.map[y].length; x++) {
                // 地形数据
                numericMap[y][x] = this.map[y][x].type;
            }
        }
        return numericMap;
    }

    /**
     * 获取玩家
     * @param playerId 玩家ID
     */
    public getPlayer(playerId: string): BattlePlayer | undefined {
        return this.players.get(playerId);
    }

    /**
     * 获取所有玩家
     */
    public getAllPlayers(): BattlePlayer[] {
        return Array.from(this.players.values());
    }

    /**
     * 获取所有单位
     */
    public getAllUnits(): UnitModel[] {
        const allUnits: UnitModel[] = [];
        this.players.forEach((player) => {
            allUnits.push(...player.getAllUnits());
        });
        return allUnits;
    }

    /**
     * 获取所有建筑
     */
    public getAllBuildings(): BuildingModel[] {
        const allBuildings: BuildingModel[] = [];
        this.players.forEach((player) => {
            allBuildings.push(...player.getAllBuildings());
        });
        return allBuildings;
    }

    /**
     * 获取单位
     * @param unitId 单位ID
     */
    public getUnit(unitId: number): UnitModel | undefined {
        for (const player of this.players.values()) {
            const unit = player.getUnit(unitId);
            if (unit) return unit;
        }
        return undefined;
    }

    /**
     * 获取建筑
     * @param buildingId 建筑ID
     */
    public getBuilding(buildingId: number): BuildingModel | undefined {
        for (const player of this.players.values()) {
            const building = player.getBuilding(buildingId);
            if (building) return building;
        }
        return undefined;
    }

    /**
     * 获取单位
     * @param position 目标位置
     */
    public getUnitAt(position: { x: number; y: number }): UnitModel | undefined {
        for (const player of this.players.values()) {
            const unit = player.getUnitAt(position);
            if (unit) return unit;
        }
        return undefined;
    }

    /**
     * 获取建筑
     * @param position 目标位置
     */
    public getBuildingAt(position: { x: number; y: number }): BuildingModel | undefined {
        for (const player of this.players.values()) {
            const building = player.getBuildingAt(position);
            if (building) return building;
        }
        return undefined;
    }

    /**
     * 检查位置是否在地图边界内
     * @param position 目标位置
     * @returns 是否在边界内
     */
    public isPositionInBounds(position: { x: number; y: number }): boolean {
        return position.x >= 0 && position.x < this.map[0].length &&
               position.y >= 0 && position.y < this.map.length;
    }

    /**
     * 获取地块模型
     * @param position 目标位置
     */
    public getTildeAt(position: { x: number; y: number }): TildeModel | undefined {
        if (!this.isPositionInBounds(position)) {
            return undefined;
        }
        return this.map[position.y][position.x];
    }

    /**
     * 添加单位
     * @param unit 单位模型
     */
    public addUnit(unit: UnitModel): void {
        const player = this.players.get(unit.player);
        if (player) {
            player.addUnit(unit);
        }
    }

    /**
     * 添加建筑
     * @param building 建筑模型
     */
    public addBuilding(building: BuildingModel): void {
        const player = this.players.get(building.player);
        if (player) {
            player.addBuilding(building);
        }
    }

    /**
     * 移除单位
     * @param unitId 单位ID
     */
    public removeUnit(unitId: number): boolean {
        for (const player of this.players.values()) {
            if (player.removeUnit(unitId)) {
                return true;
            }
        }
        return false;
    }

    /**
     * 移除建筑
     * @param buildingId 建筑ID
     */
    public removeBuilding(buildingId: number): boolean {
        for (const player of this.players.values()) {
            if (player.removeBuilding(buildingId)) {
                return true;
            }
        }
        return false;
    }
}
